//! 测试作用于Option和Result上的combinator，and/or/or_else/and_then/filter/map_err/map_or/map_or_else/ok_or/ok_or_else
//! 另外，对于Option<T>可以使用as_ref()或as_mut()直接获取值的引用Option<&T>或Option<&mut T>


pub fn test() {
    // or:  s1.or(s2) = 只要s1存在就为s1，否则s2
    let s1 = Some("some1");
    let s2 = Some("some2");
    assert_eq!(s1.or(s2), s1); // s1 or s2 = s1
    let n1: Option<&str> = None;
    assert_eq!(n1.or(s1), s1); // none or s1 = s1
    let r1: Result<&str, &str> = Ok("ok1");
    let r2: Result<&str, &str> = Ok("ok2");
    let e1: Result<&str, &str> = Err("error1");
    assert_eq!(r1.or(r2), r1); // r1 or r2 = r1
    assert_eq!(e1.or(r1), r1); // none or r1 = r1

    // and: s1.and(s2) = 和javascript一样，一直往后检验，返回第一个None/Err，或者最后一个值
    assert_eq!(s1.and(s2), s2); // s1 and s2 = s2
    assert_eq!(s1.and(n1), n1); // s1 and none = none
    assert_eq!(n1.and(s1), n1); // none and s1 = none
    assert_eq!(r1.and(r2), r2); // r1 and r2 = r2
    assert_eq!(r1.and(e1), e1); // r1 and err = err
    assert_eq!(e1.and(r1), e1); // err and r1 = err

    // or_else: Some/Ok值，或者执行一个closure
    let fn_some = || Some("some2");
    let fn_none: fn() -> Option<&'static str> = || None;
    assert_eq!(s1.or_else(fn_none), s1); // s1 or ()->None = s1
    assert_eq!(n1.or_else(fn_some), s2); // none or ()->s2 = s2
    let fn_ok: fn(&'static str) -> Result<&'static str, &'static str> = |_| Ok("ok2");
    let fn_err: fn(&'static str) -> Result<&'static str, &'static str> = |_| Err("error1");
    assert_eq!(r1.or_else(fn_ok), r1); // r1 or (_)->r2 = r1
    assert_eq!(e1.or_else(fn_err), e1); // err or (_)->e1 = e1

    // and_then: 和and一样，不过then的内容换为closure
    let fn_some_then: fn(&'static str) -> Option<&'static str> = |_| Some("some2");
    let fn_err_then: fn(&'static str) -> Result<&'static str, &'static str> = |_| Ok("ok2");
    assert_eq!(s1.and_then(fn_some_then), s2); // s1 and_then ()->s2 = s2
    assert_eq!(r1.and_then(fn_err_then), r2); // r1 and_then ()->r2 = r2
    assert_eq!(e1.and_then(fn_err_then), e1); // e1 and_then ()->r2 = e1

    // filter: 如果满足closure，则返回该值，否则返回None
    let t1 = Some(3);
    let t2 = Some(6);
    let n: Option<i8> = None;
    let fn_is_even = |x: &i8| x % 2 == 0;
    assert_eq!(t1.filter(fn_is_even), n); // 3 is even = None
    assert_eq!(t2.filter(fn_is_even), t2); // 6 is even = 6
    assert_eq!(n.filter(fn_is_even), n); // none is even = none
    
    // map: 如果有值Some/Ok，则执行map->Option<T2>/Result<T2, E>，否则返回none。因此将Result<T, E> -> Result<F, E>
    let m1 = Some("abcde");
    let m2 = Some(5);
    let nm1: Option<&str> = None;
    let nm2: Option<usize> = None;
    let fn_map_str_to_i8 = |s: &str| s.chars().count();
    assert_eq!(m1.map(fn_map_str_to_i8), m2); // m1 map ()-> m2 = Option<m2>
    assert_eq!(nm1.map(fn_map_str_to_i8), nm2); // none map ()-> m2 = none
    let rm1: Result<&str, &str> = Ok("abcde");
    let rm2: Result<usize, &str> = Ok(5);
    let em1: Result<&str, &str> = Err("error");
    let em2: Result<usize, &str> = Err("error");
    let fn_map_ok_to_ok_usize = |s: &str| s.chars().count();
    assert_eq!(rm1.map(fn_map_ok_to_ok_usize), rm2); // Ok(rm1) map ()->Ok(rm2) = rm2
    assert_eq!(em1.map(fn_map_ok_to_ok_usize), em2); // Err(e1) map ()->Ok(rm2) = Err(e1)

    // map_err: 与map相反，只处理Err。因此是将Result<T, E> -> Result<T, F>

    // map_or: 将值map一下，或者给一个默认值
    const V_DEFAULT: i8 = 1;
    let mo1 = Some(10);
    let no1: Option<i8> = None;
    let fn_mo = |v: i8| v + 2;
    assert_eq!(mo1.map_or(V_DEFAULT, fn_mo), 12); // some(10) map_or (1, +2) = 12
    assert_eq!(no1.map_or(V_DEFAULT, fn_mo), V_DEFAULT); // None map_or (1, +2) = 1

    // map_or_else: 和map_or一样，但是需要提供的默认值不再是值，而是一个closure
    let fn_mo2 = || 1;
    assert_eq!(mo1.map_or_else(fn_mo2, fn_mo), 12); // some(10) map_or_else (()->1, +2) = 12
    assert_eq!(no1.map_or_else(fn_mo2, fn_mo), 1); // none map_or_else (()->1, +2) = 1

    // ok_or: Option -> Result。但是要注意，or提供的T必须是Result<_, T>的err
    let oko = Some("abcde");
    let okr: Result<&str, &str> = Ok("abcde");
    let okn: Option<&str> = None;
    let oke: Result<&str, &str> = Err("some error");
    assert_eq!(oko.ok_or("some error"), okr); // Some("abcde") ok_or Err(some error) = Ok("abcde")
    assert_eq!(okn.ok_or("some error"), oke); // none ok_or Err(some error) = Err(some error)

    // ok_or_else: 和ok_or类似，但是需要的是一个closure
    let fn_ok_err = || "some error";
    assert_eq!(oko.ok_or_else(fn_ok_err), okr); 
    assert_eq!(okn.ok_or_else(fn_ok_err), oke);
    

    // as_ref/as_mut: Option<T> -> Option<&T>
    let a: Option<&i8> = Some(&23);
    let b: Option<i8> = Some(23);
    assert_eq!(b.as_ref(), a);
}